/**
 * ref:http://blog.csdn.net/liuyunshengsir/article/details/52495919
 */
package com.sservice.web.controller.websocket;

import com.google.gson.GsonBuilder;
import com.sservice.model.entity.Notice;
import com.sservice.service.service.INoticeService;
import com.sservice.urp.dao.IUserDao;
import com.sservice.urp.vo.UserVo;
import com.sservice.web.enums.Permissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

@Component
public class WebsocketEndPoint implements WebSocketHandler {

    public static final Map<String, WebSocketSession> userSocketSessionMap;

    static {
        userSocketSessionMap = new HashMap<String, WebSocketSession>();
    }

    @Autowired
    IUserDao userDao;
    @Autowired
    INoticeService noticeService;
    private String KEY = "ID";

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String ID_ = (String) session.getAttributes().get(KEY);
        if (userSocketSessionMap.get(ID_) == null) {
            userSocketSessionMap.put(ID_, session);
        }
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        // TODO Auto-generated method stub
//        Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
//        msg.setDat/e();
//      sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));

//        super.handleTextMessage(session, message);
//        TextMessage returnMessage = new TextMessage(message.getPayload() + " received at server");
//        session.sendMessage(returnMessage);

//        session.sendMessage(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // TODO Auto-generated method stub
        if (session.isOpen()) {
            session.close();
        }
        Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        // 移除Socket会话

        removeSession(session, it);
    }

    private void removeSession(WebSocketSession session, Iterator<Entry<String, WebSocketSession>> it) {

        while (it.hasNext()) {
            Entry<String, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                break;
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Websocket:" + session.getId() + "已经关闭");
        Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        // 移除Socket会话
        removeSession(session, it);
    }

    @Override
    public boolean supportsPartialMessages() {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * 群发
     *
     * @throws
     * @Title: broadcast
     * @Description: TODO
     * @param: @param message
     * @param: @throws IOException
     * @return: void
     * @author: 刘云生
     * @Date: 2016年9月10日 下午4:23:30
     */
    public void broadcast(final TextMessage message) throws IOException {
        Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();

        // 多线程群发
        sendMsg(it, message);
    }

    /**
     * 给所有在线用户的实时页面发送消息
     *
     * @param message
     * @throws IOException
     */
    public void sendMessageToJsp(final TextMessage message, String type) throws IOException {
        Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        // 多线程群发
        sendMsg(it, message);
    }

    public Set getRelatedUser(List<Integer> userIds, String expectUserId) {
        Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        Map online = new HashMap();
        for (int i = 0; i < userIds.size(); i++) {
            String key = userIds.get(i) + "";
            if (online.get(key) == null && userSocketSessionMap.get(key) != null && !userIds.get(i).equals(Integer.valueOf(expectUserId))) {
                online.put(key, userIds.get(i));
            }
        }
        ;
        return online.keySet();
    }

    /***
     *
     * @param msg 消息主题
     * @param user 触发消息用户
     * @param type 消息类型
     * @param url 访问URL
     * @throws IOException
     */
    public void sendMsgToJsp(String msg, UserVo user, String type, String url) throws IOException {

        if (type.equals(Permissions.PurchaseOrderAuthorizedSignature)) { // 采购订单申请签章
            List<Integer> userIds = userDao.queryUserIdByPermission(Permissions.PurchaseOrderAuthorizedSignature);
            for (int i = 0; i < userIds.size(); i++) {
                if ((int) userIds.get(i) != user.getId()) { // 排除发给自己
                    Notice notice = new Notice();
                    notice.setContent(msg);
                    notice.setUrl(url);
                    Integer r = userIds.get(i);
                    notice.setReceiver(String.valueOf(r));
                    noticeService.insertSelective(notice);
                }
            }
            Set online = getRelatedUser(userIds, String.valueOf(user.getId())); // 获取相关用户
            // 多线程群发
            sendMsg(online, msg); // 群发相关用户
        }
    }

    private void sendMsg(Set it1, String message) {
        Object[] list = it1.toArray();
        for (int i = 0; i < list.length; i++) {
            WebSocketSession wss = userSocketSessionMap.get((String) list[i] + "");
            if (wss.isOpen()) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            if (wss.isOpen()) {
                                wss.sendMessage(new TextMessage(new GsonBuilder().create().toJson(message)));
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
//            }
        }
//            Entry<String, WebSocketSession> entry =  userSocketSessionMap;
//            if (entry.getValue().isOpen()) {
//                new Thread(new Runnable() {
//                    public void run() {
//                        try {
//                            if (entry.getValue().isOpen()) {
//                                entry.getValue().sendMessage(new TextMessage(new GsonBuilder().create().toJson(message)));
//                            }
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }).start();
//            }
//        }
    }

    private void sendMsg(Iterator<Entry<String, WebSocketSession>> it, TextMessage message) {
        while (it.hasNext()) {

            final Entry<String, WebSocketSession> entry = it.next();
            if (entry.getValue().isOpen()) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            if (entry.getValue().isOpen()) {
                                entry.getValue().sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }).start();
            }

        }
    }
}